package com.starview.star.compiler.format;

import java.util.Collection;
import java.util.List;

import com.starview.platform.data.IValue;
import com.starview.star.compiler.ast.Apply;
import com.starview.star.compiler.ast.BigDecimalLiteral;
import com.starview.star.compiler.ast.BooleanLiteral;
import com.starview.star.compiler.ast.CharLiteral;
import com.starview.star.compiler.ast.FloatLiteral;
import com.starview.star.compiler.ast.IAbstract;
import com.starview.star.compiler.ast.IAbstractVisitor;
import com.starview.star.compiler.ast.IntegerLiteral;
import com.starview.star.compiler.ast.LongLiteral;
import com.starview.star.compiler.ast.Name;
import com.starview.star.compiler.ast.StringLiteral;
import com.starview.star.compiler.format.rules.FmtProgram;
import com.starview.star.compiler.format.rules.FmtPtnOp.formatCode;
import com.starview.star.compiler.format.rules.FmtRule;

final class FormatVisitor implements IAbstractVisitor
{
  private final FmtProgram fmtRules;

  FormatVisitor(FmtProgram fmtRules)
  {
    this.fmtRules = fmtRules;
  }

  @Override
  public void visitApply(Apply term)
  {
    visit(term);
    term.getOperator().accept(this);
    for (IValue arg : term.getArgs())
      ((IAbstract) arg).accept(this);
  }

  @Override
  public void visitBooleanLiteral(BooleanLiteral lit)
  {
    visit(lit);
  }

  @Override
  public void visitCharLiteral(CharLiteral lit)
  {
    visit(lit);
  }

  @Override
  public void visitFloatLiteral(FloatLiteral lit)
  {
    visit(lit);
  }

  @Override
  public void visitIntegerLiteral(IntegerLiteral lit)
  {
    visit(lit);
  }

  @Override
  public void visitLongLiteral(LongLiteral lit)
  {
    visit(lit);
  }

  @Override
  public void visitName(Name name)
  {
    visit(name);
  }

  @Override
  public void visitStringLiteral(StringLiteral str)
  {
    visit(str);
  }

  private void visit(IAbstract term)
  {
    List<String> categories = term.getCategories();
    if (categories != null) {
      for (String category : categories) {
        Collection<FmtRule> rules = fmtRules.rulesFor(category);

        if (rules != null)
          for (FmtRule rule : rules) {
            if (rule.applyRule(term) == formatCode.applies)
              break;
          }
      }
    }
  }

  @Override
  public void visitBigDecimal(BigDecimalLiteral lit)
  {
    visit(lit);
  }
}